﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Text;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.Queries;
using DomainDriver.DomainModeling.StorageManagers.DataSetStorage;
using DomainDriver.DomainModeling.StorageManagers.EntityFrameworkStorage;
using AutomotivePricingModel.ValueObjects.YearlyFinancialAssessments;
using ObjectRow = AutomotivePricingModel.AutomotivePricingDataSet.VehiclesRow;

namespace AutomotivePricingModel.Vehicles
{
    public partial class Vehicle : IEfEntity<Guid>, IEfAggregateRoot<Vehicle>, IDataSetSerializable<AutomotivePricingDataSet, DataRow>
    {
        #region ADO .NET Entities Framework Storage

        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public Guid EF_Key
        {
            get { return m_Key; }
            set { m_Key = value; }
        }

        [Required]
        public OptionsConfiguration EF_OptionsConfiguration
        {
            get { return m_OptionsConfiguration; }
            set { m_OptionsConfiguration = value; }
        }

        [Required]
        [Association("Assc_Vehicle_YearlyFinancialAssessment", "EF_PriceHistoryId", "EF_YearlyFinancialAssessmentId")]
        [ForeignKey("EF_PriceHistory")]
        public Nullable<Guid> EF_PriceHistoryId
        {
            get { return m_PriceHistoryId; }
            set { m_PriceHistoryId = value; }
        }

        [Required]
        public YearlyFinancialAssessment EF_PriceHistory
        {
            get
            {
                if (!m_PriceHistoryId.HasValue)
                { return null; }
                if (!m_PriceHistory.Key.Equals(m_PriceHistoryId.Value))
                { return null; }
                return m_PriceHistory;
            }
            set
            {
                if (!m_PriceHistoryId.HasValue)
                { throw new ApplicationException(); }
                if (m_PriceHistoryId.Value != value.Key)
                { throw new ApplicationException(); }
                m_PriceHistory = value;
            }
        }

        ICollection<QuerySpecification> IEfAggregateRoot<Vehicle>.OverriddenQueries
        {
            get { return new List<QuerySpecification>(); }
        }

        bool IEfAggregateRoot<Vehicle>.SearchNestedAggregateValues(System.Data.Entity.DbContext context, IParameterizedQuery<Vehicle> query)
        {
            throw new NotImplementedException();
        }

        void IEfAggregateRoot<Vehicle>.ReadNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment assessment = YearlyFinancialAssessment.ReadValueObject(context, this.EF_PriceHistoryId.Value);
            this.EF_PriceHistory = assessment;
        }

        void IEfAggregateRoot<Vehicle>.AddNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment.AddValueObject(context, this.EF_PriceHistory);
        }

        void IEfAggregateRoot<Vehicle>.UpdateNestedAggregateValues(DbContext context, Vehicle originalAggregateRoot)
        {
            YearlyFinancialAssessment.UpdateValueObject(context, this.EF_PriceHistory, originalAggregateRoot.EF_PriceHistory);
        }

        void IEfAggregateRoot<Vehicle>.DeleteNestedAggregateValues(DbContext context)
        {
            YearlyFinancialAssessment.DeleteValueObject(context, this.EF_PriceHistory);
        }

        #endregion

        #region AutomotivePricingDataSet Serialization

        string IDataSetSerializable<AutomotivePricingDataSet, DataRow>.ObjectTableName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.Vehicles.TableName; }
        }

        string IDataSetSerializable<AutomotivePricingDataSet, DataRow>.KeyColumnName
        {
            get { return AutomotivePricingDataSet.SchemaHelper.Vehicles.EF_VehicleIdColumn.ColumnName; }
        }

        void IDataSetSerializable<AutomotivePricingDataSet, DataRow>.Serialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            objectRecord.EF_VehicleId = m_Key;
            DataSetSerializationUtilities.SerializeNullableField<int>(m_ModelYear, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.ModelYearColumn);
            DataSetSerializationUtilities.SerializeNullableField<Guid>(m_ParentProductionModel, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.ParentProductionModelColumn);
            DataSetSerializationUtilities.SerializeNullableField<Guid>(m_PriceHistoryId, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.EF_PriceHistoryIdColumn);

            objectRecord.EF_OptionsConfiguration_EF_BodyStyle = m_OptionsConfiguration.EF_BodyStyle;
            objectRecord.EF_OptionsConfiguration_EF_DriveTrainType = m_OptionsConfiguration.EF_DriveTrainType;
            objectRecord.EF_OptionsConfiguration_EF_TransmissionType = m_OptionsConfiguration.EF_TransmissionType;
            objectRecord.EF_OptionsConfiguration_EngineSizeInLiters = m_OptionsConfiguration.EngineSizeInLiters;
            objectRecord.EF_OptionsConfiguration_HasNavigationSystem = m_OptionsConfiguration.HasNavigationSystem;
            objectRecord.EF_OptionsConfiguration_NumberOfCylinders = m_OptionsConfiguration.NumberOfCylinders;
            objectRecord.EF_OptionsConfiguration_NumberOfSpeeds = m_OptionsConfiguration.NumberOfSpeeds;

            DataRow nestedObjectRow = datasource.Tables[m_PriceHistory.ObjectTableName].NewRow();
            m_PriceHistory.Serialize(datasource, nestedObjectRow);
        }

        void IDataSetSerializable<AutomotivePricingDataSet, DataRow>.Deserialize(AutomotivePricingDataSet datasource, DataRow dataRow)
        {
            ObjectRow objectRecord = dataRow as ObjectRow;

            m_Key = objectRecord.EF_VehicleId;
            DataSetSerializationUtilities.DeserializeNullableField<int>(out m_ModelYear, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.ModelYearColumn);
            DataSetSerializationUtilities.DeserializeNullableField<Guid>(out m_ParentProductionModel, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.ParentProductionModelColumn);
            DataSetSerializationUtilities.DeserializeNullableField<Guid>(out m_PriceHistoryId, objectRecord, AutomotivePricingDataSet.SchemaHelper.Vehicles.EF_PriceHistoryIdColumn);

            m_OptionsConfiguration.EF_BodyStyle = objectRecord.EF_OptionsConfiguration_EF_BodyStyle;
            m_OptionsConfiguration.EF_DriveTrainType = objectRecord.EF_OptionsConfiguration_EF_DriveTrainType;
            m_OptionsConfiguration.EF_TransmissionType = objectRecord.EF_OptionsConfiguration_EF_TransmissionType;
            m_OptionsConfiguration.EngineSizeInLiters = objectRecord.EF_OptionsConfiguration_EngineSizeInLiters;
            m_OptionsConfiguration.HasNavigationSystem = objectRecord.EF_OptionsConfiguration_HasNavigationSystem;
            m_OptionsConfiguration.NumberOfCylinders = objectRecord.EF_OptionsConfiguration_NumberOfCylinders;
            m_OptionsConfiguration.NumberOfSpeeds = objectRecord.EF_OptionsConfiguration_NumberOfSpeeds;

            m_PriceHistory.Deserialize(datasource, objectRecord.YearlyFinancialAssessmentsRow);
        }

        #endregion
    }
}